import 'dart:async';
import 'dart:io';

import 'package:connectivity_plus/connectivity_plus.dart';
import 'package:dio/dio.dart';
import 'package:flutter/material.dart';
import 'package:log4f/log4f.dart';

class ConnectStateUtil {
  static ConnectStateUtil? _instance;
  final Connectivity _connectivity = Connectivity();
  final List<_ConnectStateListener> _listens = [];
  StreamSubscription<ConnectivityResult>? _subscription;

  ConnectStateUtil._() {
    _subscription = _connectivity.onConnectivityChanged.listen((ConnectivityResult result) {
      for (var connectUtilListen in _listens) {
        connectUtilListen.listener(result);
      }
    });
  }

  factory ConnectStateUtil.listen(String id, void Function(ConnectivityResult result) listener) {
    instance.removeListen(id);
    instance._listens.add(_ConnectStateListener(id, listener));
    return instance;
  }

  static ConnectStateUtil get instance => _instance ??= ConnectStateUtil._();

  Future<bool> get isBluetooth async => ConnectivityResult.bluetooth == await _connectivity.checkConnectivity();

  Future<bool> get isWifi async => ConnectivityResult.wifi == await _connectivity.checkConnectivity();

  Future<bool> get isEthernet async => ConnectivityResult.ethernet == await _connectivity.checkConnectivity();

  Future<bool> get isMobile async => ConnectivityResult.mobile == await _connectivity.checkConnectivity();

  Future<bool> get isVpn async => ConnectivityResult.vpn == await _connectivity.checkConnectivity();

  Future<bool> get isNone async => ConnectivityResult.none == await _connectivity.checkConnectivity();

  Future<bool> get hasNetwork async {
    try {
      List<InternetAddress> result = await InternetAddress.lookup('storage.flutter-io.cn');
      return result.isNotEmpty && result[0].rawAddress.isNotEmpty;
    } on SocketException {
      return false;
    }
  }

  Future<bool> canAccess(String url) async {
    try {
      if (url.startsWith("http")) {
        Dio dio = Dio(BaseOptions(sendTimeout: 3000, connectTimeout: 3000, receiveTimeout: 3000));
        dio.interceptors.add(LogInterceptor(request: false, requestBody: true, responseBody: true));
        Response response = await dio.head(url);
        dio.close(force: true);
        return response.statusCode == 200;
      } else if (url.startsWith("ws")) {
        WebSocket webSocket = await WebSocket.connect(url, customClient: HttpClient()..connectionTimeout = const Duration(seconds: 3));
        bool open = webSocket.readyState == WebSocket.open;
        webSocket.close();
        return open;
      } else {
        return false;
      }
    } on DioError catch (e) {
      return e.type == DioErrorType.response;
    } catch (e) {
      // debugPrint("无法访问：${e.toString()}");
      Log4f.e(msg: e.toString(), tag: "无法访问");
      return false;
    }
  }

  // Future<NetworkState> refreshNetworkStateEntity() {
  //   Completer<NetworkState> completer = Completer<NetworkState>();
  //   Future.wait([hasNetwork, isWifi, WiFiForIoTPlugin.getSSID()]).then((values) {
  //     bool hasNetwork = values[0] as bool;
  //     bool isWifi = values[1] as bool;
  //     String? ssid = values[2].toString();
  //     NetworkState networkState = NetworkState(hasNetwork, isWifi, ssid);
  //     debugPrint("网络状态 => $networkState");
  //     completer.complete(networkState);
  //     Global.navigatorKey.currentContext?.read<NetworkStateNotifier>().setState(networkState);
  //   });
  //   return completer.future;
  // }

  void removeListen(String id) {
    _listens.removeWhere((_ConnectStateListener connectUtilListen) => connectUtilListen.id == id);
  }

  void dispose() {
    _listens.clear();
    _subscription?.cancel();
    _subscription = null;
  }
}

class _ConnectStateListener {
  String id;
  void Function(ConnectivityResult result) listener;

  _ConnectStateListener(this.id, this.listener);
}
